package modelcontroller;

import gui.ChatGUI;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.logging.Level;
import java.util.logging.Logger;
import network.ChatNI;

/**
 *
 * @author Mariam
 */
public class ChatController {

    private ChatModel model;
    private ChatGUI gui;
    private ChatNI ni;
    private String filepath;

    /**
     * Constructs the controller which will manage the model, GUI, and network
     * interface specified
     *
     * @param model model
     * @param gui GUI
     * @param ni the network interface
     */
    public ChatController(ChatModel model, ChatGUI gui, ChatNI ni) {
        this.model = model;
        this.gui = gui;
        this.ni = ni;
    }

    /**
     * Handles the demand of connection of the local user
     *
     * @param username login entered by the local user
     */
    public void performConnect(String username) {
        try {
            User localUser = new User(username, InetAddress.getLocalHost().getHostName());
            model.setLocalUser(localUser);
            model.setLocalUserIsConnected(true);
        } catch (UnknownHostException ex) {
            Logger.getLogger(ChatController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Handles the demand of disconnection of the local user
     */
    public void performDisconnect() {
        model.setLocalUserIsConnected(false);
    }

    /**
     * Handles the selection of a remote user made by the local user
     *
     * @param remoteUser
     */
    public void performUserSelected(User remoteUser) {
        if (model.getHashmapConv().get(remoteUser) == null) {
            Conversation c = model.createConversation(remoteUser);
            gui.displayNewConversation(c);
        }
    }

    /**
     * Handles the reception of a hello message sent by a remote user
     *
     * @param username login of the remote user
     * @param hostname name of the machine used to send the message
     */
    public void performHelloRcvd(String username, String hostname) {
        User newUser = new User(username, hostname);
        model.addUser(newUser);
    }

    /**
     * Handles the reception of a text message sent by a remote user
     *
     * @param remoteUser the sender remote user
     * @param msg the text message received
     */
    public void performMsgRcvd(User remoteUser, String msg) {
        Conversation c = model.getHashmapConv().get(remoteUser);
        String username = remoteUser.getUsername();
        if (c != null) {
            c.addMessage(username + " :  " + msg);
        } else {
            c = model.createConversation(remoteUser);
            c.addMessage(username + " :  " + msg);
            gui.displayNewConversation(c);
        }
        model.updateConversations();
    }

    /**
     * Handles the reception of a bye message sent by a remote user
     *
     * @param remoteUser the sender remote user
     */
    public void performByeRcvd(User remoteUser) {
        model.removeUser(remoteUser);
        String username = remoteUser.getUsername();
        Conversation conversation = model.getHashmapConv().get(remoteUser);
        if (conversation != null) {
            conversation.addMessage(username + " : ---- DISCONNECTED ----");
            model.updateConversations();
        }
    }

    /**
     * Handles the reception of a file request sent by a remote user
     *
     * @param username login of the remote user
     * @param filename name of the file that the remote user wants to send to
     * the local user
     * @param size size of the file
     */
    public void performFileRequestRcvd(String username, String filename, long size) {
        boolean accepted = gui.displayFileRequest(username, filename);
        performSendFileAnswer(username, filename, accepted, size);
    }

    /**
     * Handles the reception of a file answer (the response of the remote user
     * to a file request sent by the local user)
     *
     * @param username login of the remote user
     * @param filename name of the file indicated in the file request (the file
     * the local user wants to send)
     * @param accepted response : true if the remote used wants to download the
     * file, false if he refuses the sending of the file
     */
    public void performFileAnswerRcvd(String username, String filename, boolean accepted) {
        String message;
        Conversation c = model.getHashmapConv().get(model.getHashmapUsers().get(username));
        if (!accepted) {
            message = ": I don't want to download the file '";
        } else {
            message = ": I want to download the file '";
        }
        c.addMessage(username + message + filename + "'");
        model.updateConversations();
        if (accepted) {
            performSendFile(username);
        }
    }

    /**
     * Handles the demand of the local user to send a text message
     *
     * @param username login of the remote user to whom the message is sent
     * @param message text that the local user wants to send
     */
    public void performSendMessage(String username, String message) {
        ni.sendMsg(username, message);
        Conversation c = model.getHashmapConv().get(model.getHashmapUsers().get(username));
        c.addMessage(model.getLocalUser().getUsername() + " :  " + message);
        model.updateConversations();
    }

    /**
     * Handles the demand of the local user to send a file
     *
     * @param username login of the remote user to whom the request is sent
     * @param filename name of the file he wants to send
     * @param filepath path to indicates where is located the file
     * @param size size of the file
     */
    public void performSendFileRequest(String username, String filename, String filepath, long size) {
        ni.sendFileRequest(username, filename, size);
        Conversation c = model.getHashmapConv().get(model.getHashmapUsers().get(username));
        c.addMessage(model.getLocalUser().getUsername() + " :  I want to send you this file '" + filename + "'");
        model.updateConversations();
        this.filepath = filepath;
    }

    /**
     * Handles the local user's reply to a file request sent by a remote user
     *
     * @param username the login of the remote user
     * @param filename name of the file the remote user wants to send
     * @param accepted the response of the local user
     * @param size size of the file
     */
    public void performSendFileAnswer(String username, String filename, boolean accepted, long size) {
        String message;
        Conversation c = model.getHashmapConv().get(model.getHashmapUsers().get(username));
        if (!accepted) {
            message = ": I don't want to download the file '";
        } else {
            message = ": I want to download the file '";
            filepath = performAskFilepath();
        }
        c.addMessage(model.getLocalUser().getUsername() + message + filename + "'");
        model.updateConversations();
        if (accepted) {
            ni.receiveFile(filename, filepath);
            c.addMessage(model.getLocalUser().getUsername() + " :  FILE RECEIVED ");
            model.updateConversations();
        }
        ni.sendFileAnswer(username, filename, accepted, size);
    }

    /**
     * Handles the sending of the last file the local user has indicated
     *
     * @param username the login of the remote user
     */
    public void performSendFile(String username) {
        ni.sendFile(username, this.filepath);
        Conversation c = model.getHashmapConv().get(model.getHashmapUsers().get(username));
        c.addMessage(model.getLocalUser().getUsername() + " :  FILE SENT");
        model.updateConversations();
    }

    private String performAskFilepath() {
        return gui.displayFileChooser();
    }
}
